import {
  Authenticator,
  CheckboxField,
  useAuthenticator,
} from '@aws-amplify/ui-react';

import { Example } from '@/components/Example';
import { InlineFilter } from '@/components/InlineFilter';

## Sign Up Field Order

The authenticator allows a custom order of sign up fields on the Sign Up page.

Order is determined by a `formFields` prop that is passed into the Authenticator component.
This prop will have the `signUp` key with a list of all the input fields. Each input field will
have an `order` key that specifies which order it will be displayed on the page.

In the example below the order will be set as `email`, `family_name`, `birthdate`, `preferred_username`, `password` and finally `confirm_password`.

**Note:** Fields that do not have a `order` key will be displayed at the bottom of the Sign Up page. The `order` key can also be combined with other form field updates. In addition, typically attributes added to the sign up page have already been inferred through [Zero Configuration](./configuration#sign-up-attributes). However, you can explicitly set the [sign up attributes prop](./configuration#sign-up-attributes) to add these to the sign up page if needed.

<InlineFilter filters={['angular']}>
_app.component.html_

```html{1}
<amplify-authenticator [formFields]="formFields" [signUpAttributes]="signUpAttributes">
  <ng-template
    amplifySlot="authenticated"
    let-user="user"
    let-signOut="signOut"
  >
    <h2>Welcome, {{ user.username }}!</h2>
    <button (click)="signOut()">Sign Out</button>
  </ng-template>
</amplify-authenticator>
```

_app.component.ts_

```js
import { Component } from '@angular/core';
import { Amplify } from 'aws-amplify';

// import config from './aws-exports'; // Amplify Gen 1 config
import config from './amplify_outputs.json'

@Component({
  selector: 'app',
  templateUrl: 'app.component.html',
})
export class AppComponent {
  constructor() {
    Amplify.configure(config);
  }

  public formFields = {
    signUp: {
      email: {
        order:1
      },
      family_name: {
        order: 2
      },
      preferred_username: {
        order: 4
      },
      birthdate: {
        order: 3
      },
      password: {
        order: 5
      },
      confirm_password: {
        order: 6
      }
    },
  }
}

// Adding the signUpAttributes prop is typically not needed since attributes are inferred via Zero Configuration.
// For the sake of this example they have been explicitly added so you can copy and paste this into your own application and see it work. 
public signUpAttributes={['birthdate', 'family_name', 'preferred_username']}
```
</InlineFilter>
<InlineFilter filters={['react']}>
```tsx{3-9, 17}

const formFields = {
   signUp: {
     email: {
       order:1
     },
     family_name: {
       order: 2
     },
     preferred_username: {
       order: 4
     },
     birthdate: {
       order: 3
     },
     password: {
       order: 5
     },
     confirm_password: {
       order: 6
     }
   },
  }


// Adding the signUpAttributes prop is typically not needed since attributes are inferred via Zero Configuration.
// For the sake of this example they have been explicitly added so you can copy and paste this into your own application and see it work. 
const signUpAttributes={['birthdate', 'family_name', 'preferred_username']}

export default function App() {
  return (
    <Authenticator formFields={formFields} signUpAttributes={signUpAttributes}>
      {({ signOut }) => <button onClick={signOut}>Sign out</button>}
    </Authenticator>
  );
}
```
</InlineFilter>
<InlineFilter filters={['vue']}>
```html{3}
<script setup>
const formFields = {
    signUp: {
      email: {
        order:1
      },
      family_name: {
        order: 2
      },
      preferred_username: {
        order: 4
      },
      birthdate: {
        order: 3
      },
      password: {
        order: 5
      },
      confirm_password: {
        order: 6
      }
    },
}



// Adding the signUpAttributes prop is typically not needed since attributes are inferred via Zero Configuration.
// For the sake of this example they have been explicitly added so you can copy and paste this into your own application and see it work. 
const signUpAttributes={['birthdate', 'family_name', 'preferred_username']}
</script>
<template>
  <authenticator :form-fields="formFields" :sign-up-attributes="signUpAttributes">
    <template v-slot="{ user, signOut }">
      <h1>Hello {{ user.username }}!</h1>
      <button @click="signOut">Sign Out</button>
    </template>
  </authenticator>
</template>
```
</InlineFilter>
<InlineFilter filters={['svelte']}>
```html
<script lang="ts">
  import { Amplify } from 'aws-amplify';
  import { Authenticator } from '@aws-amplify/ui-svelte'
  import "@aws-amplify/ui-svelte/styles.css";
  import awsconfig from './aws-exports';

  Amplify.configure(awsconfig);

  const formFields = {
    signUp: {
      email: {
        order:1
      },
      family_name: {
        order: 2
      },
      preferred_username: {
        order: 4
      },
      birthdate: {
        order: 3
      },
      password: {
        order: 5
      },
      confirm_password: {
        order: 6
      }
    },
  }

  // Adding the signUpAttributes prop is typically not needed since attributes are inferred via Zero Configuration.
  // For the sake of this example they have been explicitly added so you can copy and paste this into your own application and see it work.
  const signUpAttributes={['birthdate', 'family_name', 'preferred_username']}
</script>

<Authenticator {formFields} {signUpAttributes}>
  {#snippet children({ user, signOut })}
    <h1>Hello {user.username}!</h1>
    <button onclick={signOut}>Sign Out</button>
  {/snippet}
</Authenticator>
```
</InlineFilter>

<Example>
  <Authenticator
    initialState={'signUp'}
    loginMechanisms={['email']}
    signUpAttributes={['birthdate', 'family_name', 'preferred_username']}
    formFields={{
      signUp: {
        email: {
          order: 1
        },
        family_name: {
          order: 2
        },
        preferred_username: {
          order: 4
        },
        birthdate: {
          order: 3
        },
        password: {
          order: 5
        },
        confirm_password: {
          order: 6
        }
      },
    }}

/>

</Example>

## Form Field Customization

The Authenticator allows for customization of multiple aspects of the form fields.
The sections below will describe several use cases, on how to modify these fields.

Overall, the following attributes are allowed to be modified on any input as described in the
[labels and placeholder](#updating-labels-placeholders-required-fields-and-showing-labels) section:

`placeholder`
`label`

Additionally, you'll be able to show or hide the `label` of each form field by using `labelHidden` and set a field to required or not required with `isRequired`.

For customers wishing to change a phone number field, a new `dialCode` and `dialCodeList` key are now available as described in the
[dialCode](#default-international-dial-code) and [dialCodeList](#change-dial-code-list).

For a full list of component names and field names can be found in the [input form table](#input-form-field-names-table).

### Updating labels, placeholders, required fields and showing labels

You can customize any label, placeholder, set a field as required or not required, and hide or show labels by configuring the `formFields` props, and passing it into the Authenticator component.
To use this feature create a `formFields` prop and include the component name as a key.
Inside that object you can list all the inputs you'd like to change by their name. Inputs can have additional client side validation by following [HTML form validation standards](https://developer.mozilla.org/en-US/docs/Learn/Forms/Form_validation).

**Note:** Specifying `formFields` for a given field will overwrite any default attributes. To include defaults, you must re-specify them as shown below.

The following example customizes the Sign In page by:

- Updating the placeholder with `placeholder`.
- Setting required to true with `isRequired`. `username` is required by default, but as mentioned above, default attributes will be overwritten and must be re-declared when using `formFields`.
- Updating the label text with `label`.
- Show the label using `labelHidden` set to `false`.

**Note:** On the sign in page the input name is always `username`, regardless of the login mechanism type.

<InlineFilter filters={['angular']}>
_app.component.ts_

```js
import { Component } from '@angular/core';
import { Amplify } from 'aws-amplify';

// import config from './aws-exports'; // Amplify Gen 1 config
import config from './amplify_outputs.json'


@Component({
  selector: 'app',
  templateUrl: 'app.component.html',
})
export class AppComponent {
  constructor() {
    Amplify.configure(config);
  }
  public formFields = {
    signIn: {
      username: {
        placeholder: 'Enter Your Email Here',
        isRequired: true,
        label: 'Email:'
      },
    },
  };
}
```

_app.component.html_

```html{1}
<amplify-authenticator [formFields]="formFields">
  <ng-template
    amplifySlot="authenticated"
    let-user="user"
    let-signOut="signOut"
  >
    <h2>Welcome, {{ user.username }}!</h2>
    <button (click)="signOut()">Sign Out</button>
  </ng-template>
</amplify-authenticator>
```
</InlineFilter>
<InlineFilter filters={['react']}>
```tsx{3-10, 17}

const formFields = {
  signIn: {
    username: {
      placeholder: 'Enter Your Email Here',
      isRequired: true,
      label: 'Email:'
    },
  },
}

export default function App() {
  return (
    <Authenticator formFields={formFields}>
      {({ signOut }) => <button onClick={signOut}>Sign out</button>}
    </Authenticator>
  );
}
```
</InlineFilter>
<InlineFilter filters={['vue']}>
```html{3}
<script setup>
const formFields = {
  signIn: {
    username: {
      placeholder: 'Enter Your Email Here',
      isRequired: true,
      label: 'Email:'
    },
  },
}
</script>
<template>
  <authenticator :form-fields="formFields">
    <template v-slot="{ user, signOut }">
      <h1>Hello {{ user.username }}!</h1>
      <button @click="signOut">Sign Out</button>
    </template>
  </authenticator>
</template>
```
</InlineFilter>
<InlineFilter filters={['svelte']}>
```html
<script lang="ts">
  import { Amplify } from 'aws-amplify';
  import { Authenticator } from '@aws-amplify/ui-svelte'
  import "@aws-amplify/ui-svelte/styles.css";
  import awsconfig from './aws-exports';

  Amplify.configure(awsconfig);

  const formFields = {
    signIn: {
      username: {
        placeholder: 'Enter Your Email Here',
        isRequired: true,
        label: 'Email:'
      },
    },
  }
</script>

<Authenticator {formFields}>
  {#snippet children({ user, signOut })}
    <h1>Hello {user.username}!</h1>
    <button onclick={signOut}>Sign Out</button>
  {/snippet}
</Authenticator>
```
</InlineFilter>

<Example>
  <Authenticator
    loginMechanisms={['email']}
    formFields={{
      signIn: {
        username: {
          placeholder: 'Enter Your Email Here',
          isRequired: true,
          label: 'Email:'
        },
      }
    }}
/>

</Example>

### Default international dial code

Default Dial code customization is available via the `dialCode` form field key.

The following example will set the default dial code to `+227` on the Sign Up and Sign In page.

<InlineFilter filters={['angular']}>
_app.component.html_

```html{1}
<amplify-authenticator [formFields]="formFields">
  <ng-template
    amplifySlot="authenticated"
    let-user="user"
    let-signOut="signOut"
  >
    <h2>Welcome, {{ user.username }}!</h2>
    <button (click)="signOut()">Sign Out</button>
  </ng-template>
</amplify-authenticator>
```

_app.component.ts_

```js
import { Component } from '@angular/core';
import { Amplify } from 'aws-amplify';

// import config from './aws-exports'; // Amplify Gen 1 config
import config from './amplify_outputs.json'


@Component({
  selector: 'app',
  templateUrl: 'app.component.html',
})
export class AppComponent {
  constructor() {
    Amplify.configure(config);
  }
  public formFields = {
    signIn: {
      username: {
        dialCode: "+227"
      },
    },
    signUp: {
      phone_Number: {
        dialCode: "+227"
      },
    },
  };
}
```
</InlineFilter>
<InlineFilter filters={['react']}>
```tsx{3-10, 17}

const formFields = {
  signIn: {
    username: {
      dialCode: '+227'
    },
  },
  signUp: {
    phone_number: {
      dialCode: '+227'
    },
  },
}

export default function App() {
  return (
    <Authenticator formFields={formFields}>
      {({ signOut }) => <button onClick={signOut}>Sign out</button>}
    </Authenticator>
  );
}
```
</InlineFilter>
<InlineFilter filters={['vue']}>
```html{3}
<script setup>
const formFields = {
  signIn: {
    username: {
      dialCode: '+227'
    },
  },
  signUp: {
    phone_number: {
      dialCode: '+227'
    },
  },
}
</script>
<template>
  <authenticator :form-fields="formFields">
    <template v-slot="{ user, signOut }">
      <h1>Hello {{ user.username }}!</h1>
      <button @click="signOut">Sign Out</button>
    </template>
  </authenticator>
</template>
```
</InlineFilter>

<InlineFilter filters={['svelte']}>
```html
<script lang="ts">
  import { Amplify } from 'aws-amplify';
  import { Authenticator } from '@aws-amplify/ui-svelte'
  import "@aws-amplify/ui-svelte/styles.css";
  import awsconfig from './aws-exports';

  Amplify.configure(awsconfig);

  const formFields = {
    signIn: {
      username: {
        dialCode: '+227'
      },
    },
    signUp: {
      phone_number: {
        dialCode: '+227'
      },
    },
  }
</script>

<Authenticator {formFields}>
  {#snippet children({ user, signOut })}
    <h1>Hello {user.username}!</h1>
    <button onclick={signOut}>Sign Out</button>
  {/snippet}
</Authenticator>
```
</InlineFilter>

<Example>
  <Authenticator
    loginMechanisms={['phone_number']}
    formFields={{
      signIn: {
        username: {
          dialCode: '+227',
        },
      },
      signUp: {
        phone_number: {
          dialCode: '+227',
        },
      },
    }}
  />
</Example>

### Change dial code list

If needed, you can update the list of dial codes shown to the user by assigning an array of dial codes to the `dialCodeList`.

In this example, only four dial codes are show in the drop down list for the sign in and sign up pages.

**Note:** Make sure to add the plus sign to each dial code in the `dialCodeList`.

<InlineFilter filters={['angular']}>
_app.component.html_

```html{1}
<amplify-authenticator [formFields]="formFields">
  <ng-template
    amplifySlot="authenticated"
    let-user="user"
    let-signOut="signOut"
  >
    <h2>Welcome, {{ user.username }}!</h2>
    <button (click)="signOut()">Sign Out</button>
  </ng-template>
</amplify-authenticator>
```

_app.component.ts_

```js
import { Component } from '@angular/core';
import { Amplify } from 'aws-amplify';

// import config from './aws-exports'; // Amplify Gen 1 config
import config from './amplify_outputs.json'

@Component({
  selector: 'app',
  templateUrl: 'app.component.html',
})
export class AppComponent {
  constructor() {
    Amplify.configure(config);
  }
  public formFields = {
    signIn: {
      username: {
       dialCodeList: ['+1', '+123', '+227', '+229']
      },
    },
    signUp: {
      phone_Number: {
        dialCodeList: ['+1', '+123', '+227', '+229']
      },
    },
  };
}
```
</InlineFilter>
<InlineFilter filters={['react']}>
```tsx{3-10, 17}

const formFields = {
  signIn: {
    username: {
      dialCodeList: ['+1', '+123', '+227', '+229']
    },
  },
  signUp: {
    phone_number: {
      dialCodeList: ['+1', '+123', '+227', '+229']
    },
  },
}

export default function App() {
  return (
    <Authenticator formFields={formFields}>
      {({ signOut }) => <button onClick={signOut}>Sign out</button>}
    </Authenticator>
  );
}
```
</InlineFilter>
<InlineFilter filters={['vue']}>
```html{3}
<script setup>
const formFields = {
  signIn: {
    username: {
      dialCodeList: ['+1', '+123', '+227', '+229']
    },
  },
  signUp: {
    phone_number: {
      dialCodeList: ['+1', '+123', '+227', '+229']
    },
  },
}
</script>
<template>
  <authenticator :form-fields="formFields">
    <template v-slot="{ user, signOut }">
      <h1>Hello {{ user.username }}!</h1>
      <button @click="signOut">Sign Out</button>
    </template>
  </authenticator>
</template>
```
</InlineFilter>

<InlineFilter filters={['svelte']}>
```html
<script lang="ts">
  import { Amplify } from 'aws-amplify';
  import { Authenticator } from '@aws-amplify/ui-svelte'
  import "@aws-amplify/ui-svelte/styles.css";
  import awsconfig from './aws-exports';

  Amplify.configure(awsconfig);

  const formFields = {
    signIn: {
      username: {
        dialCodeList: ['+1', '+123', '+227', '+229']
      },
    },
    signUp: {
      phone_number: {
        dialCodeList: ['+1', '+123', '+227', '+229']
      },
    },
  }
</script>

<Authenticator {formFields}>
  {#snippet children({ user, signOut })}
    <h1>Hello {user.username}!</h1>
    <button onclick={signOut}>Sign Out</button>
  {/snippet}
</Authenticator>
```
</InlineFilter>

<Example>
  <Authenticator
    loginMechanisms={['phone_number']}
    formFields={{
      signIn: {
        username: {
          dialCodeList: ['+1', '+123', '+227', '+229'] 
        },
      },
      signUp: {
        phone_number: {
          dialCodeList: ['+1', '+123', '+227', '+229'] 
        }
      }
    }}
/>

</Example>

### Input Form Field Names Table

Here are the various components and input names that are available for customization.

| Component Name         | Form Field Names                                                                                                                                                                |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `signIn`               | `username` `password`                                                                                                                                                           |
| `signUp`               | `email` `phone_number` `username` `password` `confirm_password` `preferred_username` `birthdate` `family_name` `middle_name` `given_name` `name` `nickname` `profile` `website` |
| `confirmSignUp`        | `confirmation_code`                                                                                                                                                             |
| `forgotPassword`       | `username`                                                                                                                                                                     |
| `confirmResetPassword` | `confirmation_code` `password` `confirm_password`                                                                                                                               |
| `forceNewPassword`     | `password` `confirm_password`                                                                                                                                                   |
| `setupTotp`            | `confirmation_code`                                                                                                                                                             |
| `confirmSignIn`        | `confirmation_code`                                                                                                                                                             |
| `confirmVerifyUser`    | `confirmation_code`                                                                                                                                                             |
| `setupEmail`           | `email`                                                                                                                                                                         |  

**Note:** Custom sign up attributes not listed in this table are customizable. Use the form field name as the key.

## Update Setup TOTP QR Issuer and Username

When setting up TOTP you can customize the issuer and username that will be shown in TOTP applications.
This can be done by adding the `formFields` prop to the Authenticator component with a `setupTotp` key.
The `setupTotp` should have a `QR` key with a `totpIssuer` and or `totpUsername` as seen in the example below.

**Note:** Unless changed, the default `issuer` is `AWSCognito` and `username` will be the current `user.username` for the user signing up.

<InlineFilter filters={['angular']}>
_app.component.html_

```html{1}
<amplify-authenticator [formFields]="formFields">
  <ng-template
    amplifySlot="authenticated"
    let-user="user"
    let-signOut="signOut"
  >
    <h2>Welcome, {{ user.username }}!</h2>
    <button (click)="signOut()">Sign Out</button>
  </ng-template>
</amplify-authenticator>
```

_app.component.ts_

```js
import { Component } from '@angular/core';
import { Amplify } from 'aws-amplify';

// import config from './aws-exports'; // Amplify Gen 1 config
import config from './amplify_outputs.json'

@Component({
  selector: 'app',
  templateUrl: 'app.component.html',
})
export class AppComponent {
  constructor() {
    Amplify.configure(config);
  }
  public formFields = {
    setupTotp: {
      QR: {
        totpIssuer: 'test issuer',
        totpUsername: 'amplify_qr_test_user',
      },
    },
  };
}
```
</InlineFilter>
<InlineFilter filters={['react']}>
```tsx{3-9, 17}

const formFields = {
  setupTotp: {
        QR: {
          totpIssuer: 'test issuer',
          totpUsername: 'amplify_qr_test_user',
        },
      },
  }

export default function App() {
  return (
    <Authenticator formFields={formFields}>
      {({ signOut }) => <button onClick={signOut}>Sign out</button>}
    </Authenticator>
  );
}
```
</InlineFilter>
<InlineFilter filters={['vue']}>
```html{3}
<script setup>
const formFields = {
  setupTotp: {
    QR: {
      totpIssuer: 'test issuer',
      totpUsername: 'amplify_qr_test_user',
    },
  },
}
</script>
<template>
  <authenticator :form-fields="formFields">
    <template v-slot="{ user, signOut }">
      <h1>Hello {{ user.username }}!</h1>
      <button @click="signOut">Sign Out</button>
    </template>
  </authenticator>
</template>
```
</InlineFilter>
<InlineFilter filters={['svelte']}>
```html
<script lang="ts">
  import { Amplify } from 'aws-amplify';
  import { Authenticator } from '@aws-amplify/ui-svelte'
  import "@aws-amplify/ui-svelte/styles.css";
  import awsconfig from './aws-exports';

  Amplify.configure(awsconfig);

  const formFields = {
    setupTotp: {
      QR: {
        totpIssuer: 'test issuer',
        totpUsername: 'amplify_qr_test_user',
      },
    },
  }
</script>

<Authenticator {formFields}>
  {#snippet children({ user, signOut })}
    <h1>Hello {user.username}!</h1>
    <button onclick={signOut}>Sign Out</button>
  {/snippet}
</Authenticator>
```
</InlineFilter>
